package xyz.yq56.easytool.utils.collection;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

import org.springframework.util.CollectionUtils;

import xyz.yq56.easytool.utils.nvll.NullUtil;

/**
 * @author yi qiang
 * @date 2021/9/19 22:54
 */
public class CollectUtil extends CollectionUtils {

    /**
     * <br> 示例用法: toMap(list, User::getId, User::getName, (v1, v2) -> v1 + "," + v2)
     * <br> [{"id":"1","name":"yq"},{"id":"1","name":"yw"}]
     * <br> toMap映射结果 ==> {1=yq,yw}
     *
     * @param list          待处理list
     * @param keyMapper     key映射规则,例如 User::getId
     * @param valueMapper   Value映射规则,例如 User::getName
     * @param mergeFunction merge规则,当出现key相同时,前后的value怎么取舍,例如: (v1,v2)-> v1+","+v2
     * @param <T>           list中的类型,比如User
     * @param <K>           key类型,比如String
     * @param <U>           value类型,比如String
     * @return map
     */
    public static <T, K, U> Map<K, U> toMap(List<T> list
            , Function<? super T, ? extends K> keyMapper
            , Function<? super T, ? extends U> valueMapper
            , BinaryOperator<U> mergeFunction) {
        if (NullUtil.isEmpty(list)) {
            return Collections.emptyMap();
        }
        return list.stream().collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction));
    }


    /**
     * 映射为其他list
     *
     * @param list   原list
     * @param mapper 映射关系
     * @param <T>    原类型
     * @param <R>    映射类型
     * @return 映射集合
     */
    @Nullable
    public static <T, R> List<R> mapToOtherList(List<T> list, Function<? super T, ? extends R> mapper) {
        return NullUtil.apply(list, i -> i.stream().map(mapper).collect(Collectors.toList()));
    }

    /**
     * @param list      原list
     * @param predicate 过滤
     * @param <T>       原类型
     * @return 过滤后的list
     */
    @Nullable
    public static <T> List<T> filter(List<T> list, Predicate<? super T> predicate) {
        return NullUtil.apply(list, i -> i.stream().filter(predicate).collect(Collectors.toList()));
    }

    /**
     * 集合的大小
     * <br> 已判空
     *
     * @param collection 集合
     * @param <T>        泛型
     * @return 集合大小
     */
    public static <T> int size(Collection<T> collection) {
        if (CollectionUtils.isEmpty(collection)) {
            return 0;
        }
        return collection.size();
    }

    /**
     * 分组统计
     * <br> 特别好用,哈哈
     */
    public static <T, K> Map<K, Long> groupCount(List<T> list, Function<? super T, ? extends K> classifier) {
        if (CollectUtil.isEmpty(list) || classifier == null) {
            return Collections.emptyMap();
        }
        return list.stream().collect(Collectors.groupingBy(classifier, Collectors.counting()));
    }


}
